package br.unb.graphics.inference;

import java.awt.BorderLayout;
import java.awt.Dimension;

import java.util.HashMap;

import javax.swing.JLabel;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.IntervalXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class InferenceChart extends JPanel {

    public static final String BAR_CHART = "bar";
    public static final String LINE_CHART = "line";
    private ValueAxis valueaxis;
    private HashMap trafficMap;
    private double width = 1;
    private ChartPanel chartpanel;
    private XYSeriesCollection xySeriesCollection;
    private String title, xAxis, yAxis, type;

    public InferenceChart(String title, String xAxis, String yAxis, String type) {
        super(new BorderLayout());
        this.title = title;
        this.xAxis = xAxis;
        this.yAxis = yAxis;
        this.type = type;
        trafficMap = new HashMap();
        xySeriesCollection = new XYSeriesCollection();
        chartpanel = new ChartPanel(createChart(xySeriesCollection));
        chartpanel.setPreferredSize(new Dimension(500, 250));
        add(chartpanel, BorderLayout.CENTER);
    }

    /**
     * Adds a new traffic to the panel
     * @param trafficName name of the traffic to be added
     */
    public void addTraffic(String trafficName) {
        XYSeries serie = new XYSeries(trafficName);
        xySeriesCollection.addSeries(serie);
        trafficMap.put(trafficName, serie);
    }

    public void setWidth(double width) {
        this.width = width;
        xySeriesCollection.setIntervalWidth(width);
    }

    /**
     * Removes a traffic
     */
    public void removeTraffic(String trafficName) {
        xySeriesCollection.removeSeries(((XYSeries) trafficMap.get(trafficName)));
        trafficMap.remove(trafficName);
    }

    /**
     * Adds a value to the inference graphic for a given traffic
     * @param yValue y coord
     * @param xXalue x coord
     * @param trafficName Name of the traffic receiving this value
     */
    public void addValueToTraffic(double yValue, double xValue, String trafficName) {
        ((XYSeries) trafficMap.get(trafficName)).addOrUpdate(new Double(xValue), new Double(yValue));
    }

    private JFreeChart createChart(IntervalXYDataset xydataset) {

        JFreeChart jfreechart;
        if (type.equals(BAR_CHART)) {
            jfreechart = ChartFactory.createXYBarChart(
                    title, // title
                    xAxis, // x-axis label
                    false,
                    yAxis, // y-axis label
                    xydataset, // data
                    PlotOrientation.VERTICAL,
                    true, // create legend?
                    true, // generate tooltips?
                    false // generate URLs?
                    );
        } else {
            jfreechart = ChartFactory.createXYLineChart(
                    title, // title
                    xAxis, // x-axis label
                    yAxis, // y-axis label
                    xydataset, // data
                    PlotOrientation.VERTICAL,
                    true, // create legend?
                    true, // generate tooltips?
                    false // generate URLs?
                    );
        }
        XYPlot xyplot = jfreechart.getXYPlot();

        XYItemRenderer r = xyplot.getRenderer();
        if (r instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
            renderer.setDefaultEntityRadius(1);
            renderer.setDefaultShapesVisible(true);
            renderer.setDefaultShapesFilled(false);
            renderer.setDefaultLinesVisible(true);
            r.setBaseToolTipGenerator(new XYToolTipGenerator() {

                public String generateToolTip(XYDataset dataset, int series, int item) {

                    double valorY;
                    double valorX;

                    valorX = (xySeriesCollection.getSeries(series)).getDataItem(item).getX().doubleValue();
                    valorY = (xySeriesCollection.getSeries(series)).getDataItem(item).getY().doubleValue();

                    return "Y(" + valorX + ") = " + valorY;
                }
            });
        } else {
            r.setBaseToolTipGenerator(new XYToolTipGenerator() {

                public String generateToolTip(XYDataset dataset, int series, int item) {

                    double valorY;
                    double valorXStart, valorXEnd;

                    valorXStart = (xySeriesCollection.getSeries(series)).getDataItem(item).getX().doubleValue() - width / 2;
                    valorXEnd = valorXStart + width;
                    valorY = (xySeriesCollection.getSeries(series)).getDataItem(item).getY().doubleValue();

                    return "Y(" + valorXStart + " \u2264 X \u003C " + valorXEnd + ") = " + valorY + "%";
                }
            });
        }

        valueaxis = xyplot.getDomainAxis();
        valueaxis.setAutoRange(true);

        // valueaxis.setFixedAutoRange(500D);


        valueaxis = xyplot.getRangeAxis();
        // valueaxis.centerRange(0);

        //valueaxis.setRange(0,0);


        return jfreechart;
    }

    public void addLabel(JLabel label) {
        this.add(BorderLayout.SOUTH, label);
    }

    public void restart() {
        this.remove(chartpanel);
        xySeriesCollection = new XYSeriesCollection();
        chartpanel = new ChartPanel(createChart(xySeriesCollection));
        chartpanel.setPreferredSize(new Dimension(500, 270));
        this.add(chartpanel);
    }
}
